#include "Camera.h"


Camera::Camera()
{
	Camera(	0.f, 0.f, 0.f,	// pos
			0.f, 0.f, 1.f,	// look
			0.f, 1.f, 0.f,	// up
			1.f, 0.f, 0.f);	// right
}


Camera::Camera(	float posx, float posy, float posz, 
		float lookx, float looky, float lookz, 
		float upx, float upy, float upz, 
		float rightx, float righty, float rightz) : v_Pos(XMFLOAT4(posx, posy, posz, 1.0f)) , v_Look(XMFLOAT4(lookx, looky, lookz, 0.0f)), 
													v_Right(XMFLOAT4(rightx, righty, rightz, 0.0f)), v_Up(XMFLOAT4(upx, upy, upz, 0.0f))
{

	XMMATRIX tmp_Projection = XMMatrixPerspectiveFovLH(0.785f, 1.0f, 1.0f, 100.0f);
	XMStoreFloat4x4(&m_Projection, tmp_Projection);
}



Camera::~Camera()
{
	try
	{
	
	}
	catch(...)
	{
		MessageBoxA(0, "exception thrown in  destructor", 0, 0);
	}
}



void Camera::walkForward(float amount)
{
	XMVECTOR new_pos = XMLoadFloat4(&v_Pos) + amount * XMLoadFloat4(&v_Look);
	XMStoreFloat4(&v_Pos, new_pos);
	update();
}

void Camera::walkSide(float amount)
{
	XMVECTOR new_pos = XMLoadFloat4(&v_Pos) + amount * XMLoadFloat4(&v_Right);
	XMStoreFloat4(&v_Pos, new_pos);
	update();
}

void Camera::rotateY(float amount)
{
	XMMATRIX mRotate = XMMatrixRotationY(amount);
	
	XMVECTOR new_x = XMVector4Transform(XMLoadFloat4(&v_Right), mRotate);
	XMVECTOR new_z = XMVector4Transform(XMLoadFloat4(&v_Look), mRotate);
	
	XMStoreFloat4(&v_Right, new_x);
	XMStoreFloat4(&v_Look, new_z);



	update();
}


void Camera::rotateX(float amount)
{
	XMMATRIX mRotate = XMMatrixRotationAxis(XMLoadFloat4(&v_Right), amount);
	
	XMVECTOR new_y = XMVector4Transform(XMLoadFloat4(&v_Up), mRotate);
	XMVECTOR new_z = XMVector4Transform(XMLoadFloat4(&v_Look), mRotate);
	
	XMStoreFloat4(&v_Up, new_y);
	XMStoreFloat4(&v_Look, new_z);

	update();
}

void Camera::setProjection(float fovy, float aspect, float zn, float zf)
{
	XMMATRIX tmp_Projection = XMMatrixPerspectiveFovLH(fovy, aspect, zn, zf);
	XMStoreFloat4x4(&m_Projection, tmp_Projection);
}

XMMATRIX Camera::getProjectionMatrix() const
{
	return XMLoadFloat4x4(&m_Projection);
}

XMMATRIX Camera::getViewMatrix() const
{

	XMMATRIX m_view = XMMatrixIdentity();

	XMVECTOR x = -XMVector3Dot(XMLoadFloat4(&v_Right), XMLoadFloat4(&v_Pos));
	XMVECTOR y = -XMVector3Dot(XMLoadFloat4(&v_Up),    XMLoadFloat4(&v_Pos));
	XMVECTOR z = -XMVector3Dot(XMLoadFloat4(&v_Look),  XMLoadFloat4(&v_Pos));


	m_view(0,0) = v_Right.x;		m_view(0,1) = v_Up.x;			m_view(0,2) = v_Look.x; 	
	m_view(1,0) = v_Right.y;		m_view(1,1) = v_Up.y;			m_view(1,2) = v_Look.y; 
	m_view(2,0) = v_Right.z;		m_view(2,1) = v_Up.z;			m_view(2,2) = v_Look.z; 
	m_view(3,0) = XMVectorGetX(x);  m_view(3,1) = XMVectorGetY(y);  m_view(3,2) = XMVectorGetZ(z);


	return m_view;
}


void Camera::update()
{

	XMVECTOR R = XMLoadFloat4(&v_Right);
	XMVECTOR U = XMLoadFloat4(&v_Up);
	XMVECTOR L = XMLoadFloat4(&v_Look);
	XMVECTOR P = XMLoadFloat4(&v_Pos);

	L = XMVector3Normalize(L);
	U = XMVector3Normalize(XMVector3Cross(L, R));

	R = XMVector3Cross(U, L); 
	

	XMStoreFloat4(&v_Right, R);
	XMStoreFloat4(&v_Up, U);
	XMStoreFloat4(&v_Look, L);
	


}









